package com.ruoyi.driver.controller;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.ruoyi.driver.constant.HtichConstants;
import com.ruoyi.driver.domain.po.NoticePO;
import com.ruoyi.driver.entity.SessionContext;
import com.ruoyi.driver.helper.RedisSessionHelper;
import com.ruoyi.driver.service.NoticeService;
import com.ruoyi.driver.utils.LocalCollectionUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author lipengze
 * @version 1.0
 * @description: websocket 服务端
 * @date 2024/10/25 10:35
 */
@Component
@ServerEndpoint(value = "/ws/socket")
public class WsController {
    @Resource
    private NoticeService noticeService;

    //Websocket用户链接池
    //concurrent包的线程安全Map，用来存放每个客户端对应的WebSocketServer对象。
    //key是accountId，可以通过本类中的getAccountId方法获取到，value是session
    public final static Map<String, Session> pool = new ConcurrentHashMap<>();
    /**
     * 连接建立成功调用
     *
     * @param session 客户端与socket建立的会话
     * @param session 客户端的userId
     */
    @OnOpen
    public void open(Session session){
        pool.put("userid-"+session.getId(),session);
    }

    /**
     * 关闭连接时调用
     *
     * @param session 关闭连接的客户端的姓名
     */
    @OnClose
    public void close(Session session){
        //根据session获取用户id 删除session
        System.out.println("session closed");
    }

    /**
     * 用户发送ws消息，message为json格式{'receiverId':'接收人','tripId':'行程id','message':'消息内容'}
     * @param session
     * @param message
     * @throws IOException
     */
    @OnMessage
    public void message(Session session,String message) throws IOException {
        /*
         String accountId = getAccountId(session);
        NoticeHandler noticeHandler = SpringUtil.getBean(NoticeHandler.class);
        //设置相关消息内容并存入mongodb：noticeHandler.saveNotice(noticeVO);
         */
        System.out.println(message);
//        Session session2 = pool.get("1"); //发给谁
        Iterator<Session> iterator = pool.values().iterator();

        //广播给所有人
        while (iterator.hasNext()) {
            Session session2 = iterator.next();
            session2.getBasicRemote().sendText("hi,"+message);
        }

    }
    /**
     * 发生错误时候
     *
     * @param session
     * @param throwable
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        System.out.println("发生错误");
        throwable.printStackTrace();
    }
    /*
     * 在当前session中获取用户accoutId
     * */
    private String getAccountId(Session session) {
        String token = null;
        Map<String, List<String>> paramMap = session.getRequestParameterMap();
        List<String> paramList = paramMap.get(HtichConstants.SESSION_TOKEN_KEY);
        if (paramList!=null && paramList.size() != 0){
            token = paramList.get(0);
        }
        RedisSessionHelper redisSessionHelper = SpringUtil.getBean(RedisSessionHelper.class);
        if (null == redisSessionHelper) {
            return null;
        }
        SessionContext context = redisSessionHelper.getSession(token);
        boolean isisValid = redisSessionHelper.isValid(context);
        if (isisValid) {
            return context.getAccountID();
        }
        return null;
    }
    /**
     * 给指定用户发送消息
     *
     * @param noticePO 需要推送的消息
     * @throws IOException
     */
    public void pushMessage(NoticePO noticePO) {
        //获取当前会话
        Session session = pool.get(noticePO.getReceiverId());
        if (null != session && null != noticePO) {
            //获取消息体
            sendMessage(session, JSON.toJSONString(noticePO));
        }
    }

    /**
     * 发送消息
     *
     * @param session
     * @param message
     */
    private void sendMessage(Session session, String message) {
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 批量发送消息
     *
     * @param messageBOList
     */
    public void pushMessage(List<NoticePO> messageBOList) {
        if (null != messageBOList && !messageBOList.isEmpty()) {
            for (NoticePO noticePO : messageBOList) {
                pushMessage(noticePO);
            }
        }
    }
    //验证token
    private String validToken(Session session) {
        String token = getSessionToken(session);
        RedisSessionHelper redisSessionHelper = SpringUtil.getBean(RedisSessionHelper.class);
        if (null == redisSessionHelper) {
            return null;
        }
        SessionContext context = redisSessionHelper.getSession(token);
        boolean isisValid = redisSessionHelper.isValid(context);
        if (isisValid) {
            return context.getAccountID();
        }
        return null;
    }

    private String getSessionToken(Session session) {
        Map<String, List<String>> paramMap = session.getRequestParameterMap();
        List<String> paramList = paramMap.get(HtichConstants.SESSION_TOKEN_KEY);
        return LocalCollectionUtils.getOne(paramList);
    }


    /**
     * 获取在线用户
     * @return
     */
    public List<String> getInLineAccountIds() {
        return pool.keySet().stream().collect(Collectors.toList());
    }
}
